package stat;



import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import parser.Node;
import parser.SimpleNode;
import parser.Token;
import parser.XYZParserTreeConstants;
import stat.DeclarationException;

public class TypeChecking {

	private SimpleNode tree;
	private HashSet<String> intSet, longSet, boolSet;
	private String errMsg;
	HashMap<Identifier, CheckValue> classDefMap;
	private int classnum = 0;
	
	public TypeChecking (SimpleNode t){
		tree = t;
		intSet = new HashSet<String>();
		intSet.add("int");
		intSet.add(XYZParserTreeConstants.jjtNodeName[XYZParserTreeConstants.JJTINTEGERLITERAL]);
		intSet.add(XYZParserTreeConstants.jjtNodeName[XYZParserTreeConstants.JJTINTEGERTYPE]);
		
		longSet = new HashSet<String>();
		longSet.add("long");
		longSet.add(XYZParserTreeConstants.jjtNodeName[XYZParserTreeConstants.JJTLONGLITERAL]);
		longSet.add(XYZParserTreeConstants.jjtNodeName[XYZParserTreeConstants.JJTLONGTYPE]);
		
		boolSet = new HashSet<String>();
		boolSet.add("true");
		boolSet.add("false");
		boolSet.add("boolean");
		boolSet.add(XYZParserTreeConstants.jjtNodeName[XYZParserTreeConstants.JJTBOOLEANTYPE]);
		boolSet.add(XYZParserTreeConstants.jjtNodeName[XYZParserTreeConstants.JJTTRUELITERAL]);
		boolSet.add(XYZParserTreeConstants.jjtNodeName[XYZParserTreeConstants.JJTFALSELITERAL]);
		
		this.errMsg = "";
		
		/* zyytracy */
		classDefMap = new HashMap<Identifier, CheckValue>();
	}
	public void Check() throws DeclarationException{
		HashMap<Identifier,CheckValue> semanticMap = new HashMap<Identifier,CheckValue>(); 
		this.visit(semanticMap, new ArrayList<Identifier>(), tree, true);
	}
	
	
	
	
	
	private SimpleNode searchClass(SimpleNode anyNode, String className) {
		SimpleNode searchtemp = anyNode, tempclass;
		while (searchtemp.getId() != XYZParserTreeConstants.JJTSTART)
			searchtemp = (SimpleNode)searchtemp.jjtGetParent();//回到最上层
		
		for (int i = 0; i < searchtemp.jjtGetNumChildren(); ++i) {
			tempclass = (SimpleNode)searchtemp.jjtGetChild(i);
			if (tempclass.getId() == XYZParserTreeConstants.JJTCLASSDECL) {
				//tempclass = (SimpleNode)tempclass.jjtGetChild(0);//class or class extend
				tempclass = (SimpleNode)tempclass.jjtGetChild(0);//class name
				if (tempclass.jjtGetFirstToken().toString().equals(className)) {
					tempclass = (SimpleNode)tempclass.jjtGetParent();
					return tempclass;
				}
			}
		}
		return null;
	}
	
	/**
	 * 
	 * @param methodInvokeExpression JJTMETHODINVOKEEXPRESSION.
	 * @return
	 * @throws DeclarationException 
	 */
	private int callMethod(SimpleNode messageSend, HashMap<Identifier, CheckValue> map) throws DeclarationException {
		SimpleNode prefix = (SimpleNode)messageSend.jjtGetParent().jjtGetParent().jjtGetChild(0).jjtGetChild(0);//函数调用前缀(new ...() / id / this)
		SimpleNode suffix = messageSend;//函数调用后缀(method_id(..., ...))
		SimpleNode temp, searchtemp, tempclass = null;
		int index;
		boolean classfound = false;
		String classname = "";
		if (prefix.getId() == XYZParserTreeConstants.JJTTHISEXPRESSION) {
			temp = messageSend;
			while (temp.getId() != XYZParserTreeConstants.JJTSTART){
				if(temp.getId() == XYZParserTreeConstants.JJTCLASSDECL){
					classfound = true;
					tempclass = temp;
					break;
				}
				temp = (SimpleNode)temp.jjtGetParent();//退回类定义层
			}
		}
		else {
			if (prefix.getId() == XYZParserTreeConstants.JJTALLOCATIONEXPRESSION) {
				temp = (SimpleNode)prefix.jjtGetChild(0);//初始化的类名
				classname = temp.jjtGetFirstToken().toString();
				tempclass = this.searchClass(prefix, classname);
			}
			//id.id(explist),找到id的class类型
			else{
				Identifier id = new Identifier(prefix.jjtGetFirstToken().toString(),XYZParserTreeConstants.jjtmax+(++classnum));
				if(!this.DulClass(map, id.id))
					throw new DeclarationException(id.toString()+":未声明的变量.",prefix);
				tempclass = (SimpleNode)map.get(id).node;
				classname = ((SimpleNode)map.get(id).node.jjtGetChild(0)).jjtGetFirstToken().toString();
			}
			if (tempclass != null)
				classfound = true;
		}
		if (classfound) {
			//find if extends:
			boolean extend = false;
			if (((SimpleNode)tempclass.jjtGetChild(1)).getId() == XYZParserTreeConstants.JJTIDENTIFIER) {
				index = 2;
				extend = true;
			}
			else
				index = 1;
			while (index < tempclass.jjtGetNumChildren()) {
				searchtemp = (SimpleNode)tempclass.jjtGetChild(index);//类定义层的下层，是变量定义或者函数定义
				if (searchtemp.getId() == XYZParserTreeConstants.JJTMETHODDECL) {
					temp = (SimpleNode)suffix.jjtGetChild(0);//函数定义：函数名
					if (temp.jjtGetFirstToken().toString().equals(this.getChildNodeName(searchtemp, 1))) {//函数名匹配
						SimpleNode formalList = (SimpleNode)searchtemp.jjtGetChild(2);
						if (formalList.getId() == XYZParserTreeConstants.JJTFORMALLIST) {
							this.CheckFuncParam(formalList, (SimpleNode)suffix.jjtGetChild(1),map);
						}
							//this.checkFormalParameter(map, (SimpleNode)suffix.jjtGetChild(1), formalList);//检查参数列表
						
						return ((SimpleNode)searchtemp.jjtGetChild(0).jjtGetChild(0)).getId();//函数返回类型
					}
				}
				index ++;
			}
			if(extend){
				tempclass = this.searchClass(tempclass, this.getChildNodeName((SimpleNode)tempclass, 1));
				index = 1;
				while (index < tempclass.jjtGetNumChildren()) {
					searchtemp = (SimpleNode)tempclass.jjtGetChild(index);//类定义层的下层，是变量定义或者函数定义
					if (searchtemp.getId() == XYZParserTreeConstants.JJTMETHODDECL) {
						temp = (SimpleNode)suffix.jjtGetChild(0);//函数定义：函数名
						String tmpname = temp.jjtGetFirstToken().toString();
						String funname = this.getChildNodeName(searchtemp, 1);
						if (tmpname.equals(funname)) {//函数名匹配
							SimpleNode formalList = (SimpleNode)searchtemp.jjtGetChild(2);
							if (formalList.getId() == XYZParserTreeConstants.JJTFORMALLIST) {
								this.CheckFuncParam(formalList, (SimpleNode)suffix.jjtGetChild(1),map);
							}
								//this.checkFormalParameter(map, (SimpleNode)suffix.jjtGetChild(1), formalList);//检查参数列表
							
							return ((SimpleNode)searchtemp.jjtGetChild(0).jjtGetChild(0)).getId();//函数返回类型
						}
					}
					index ++;
				}
			}
		}
		return -1;
	}
	
	private String getChildNodeName(SimpleNode node, int childindex) {
		return ((SimpleNode)node.jjtGetChild(childindex)).jjtGetFirstToken().toString();
	}
	
	private boolean DulClass(HashMap<Identifier, CheckValue> map, String name) {
		boolean found = false;
		ArrayList<Identifier> list = (ArrayList<Identifier>) this.doit(map);
		for(int i = 0; i < list.size(); i++) {
			if(name.equals(list.get(i).id)){
				found = true;
				break;
			}
		}
		return found;
	}
	private void visit(HashMap<Identifier, CheckValue> map, ArrayList<Identifier> localvar, 
						SimpleNode root, boolean revert) 
						throws DeclarationException {
		HashMap<Identifier, CheckValue> coverMap = new HashMap<Identifier, CheckValue>();
		Identifier id,id1;
		String idname;
		boolean postExp = false;
		SimpleNode postRoot = null;
		try {
			switch (root.getId()) {
			case XYZParserTreeConstants.JJTSTART:
				for (int i = 0; i < root.jjtGetNumChildren(); ++i)
					this.visit(map, localvar, (SimpleNode)root.jjtGetChild(i), true);
				break;
			case XYZParserTreeConstants.JJTMAINCLASS://主类
				id = new Identifier(this.getChildNodeName(root, 0) ,XYZParserTreeConstants.JJTMAINCLASS);
				if(DulClass(map,id.id))
					throw new DeclarationException(id.toString() + ":\t重复的类的定义.", root);
				map.put(id, new CheckValue(root));	
				localvar.add(id);
				id1 = new Identifier("main" ,XYZParserTreeConstants.JJTMETHODDECL);
				if(map.containsKey(id1)) 
					throw new DeclarationException(id.toString() + ":\t重复的方法定义.", root);
				map.put(id1, new CheckValue(root));	
				localvar.add(id1);
				visit(map, new ArrayList<Identifier>(), (SimpleNode)root.jjtGetChild(1), true);
				break;
				
			case XYZParserTreeConstants.JJTCLASSDECL://类的父节点
				
				
				/* zyytracy begin*/
				map.putAll(classDefMap);
				/* zyytracy end */
				id = new Identifier(this.getChildNodeName(root, 0) ,XYZParserTreeConstants.jjtmax+(++classnum));
				if(this.DulClass(map, id.id)) 
					throw new DeclarationException(id.toString() + ":\t重复的方法定义.", root);
				map.put(id, new CheckValue(root));
				/* zyytracy begin */
				classDefMap.put(id, new CheckValue(root));
				/* zyytracy end */
				localvar.add(id);
				
				int ii = 1;
				SimpleNode child;
				if (((SimpleNode)root.jjtGetChild(1)).getId() == XYZParserTreeConstants.JJTIDENTIFIER) {
					id = new Identifier(this.getChildNodeName(root, 1) ,XYZParserTreeConstants.jjtmax+(++classnum));
					if(!this.DulClass(map, id.id))//父类未定义
						throw new DeclarationException(id.toString() + ":\t找不到父类定义.", root);
					ii = 2;
				}
				
				for(int i = ii; i < root.jjtGetNumChildren(); i++) {
					child = (SimpleNode)root.jjtGetChild(i);
					
					if (child.getId() == XYZParserTreeConstants.JJTVARDECL)
						visit(map, localvar, child, false);
					else {
						id = new Identifier(this.getChildNodeName(child, 1), XYZParserTreeConstants.JJTMETHODDECL);
						if (map.containsKey(id))
						{
							if(map.get((Identifier)id).node.jjtGetChild(2).jjtGetNumChildren() == child.jjtGetChild(2).jjtGetNumChildren())
							{
								int left = ((SimpleNode)map.get((Identifier)id).node.jjtGetChild(2).jjtGetChild(0).jjtGetChild(0)).getId();
								int right = ((SimpleNode)child.jjtGetChild(2).jjtGetChild(0).jjtGetChild(0)).getId();
								//String left = this.getChildNodeName((SimpleNode)map.get((Identifier)id).node.jjtGetChild(2), 0);
								//String right = this.getChildNodeName((SimpleNode)child.jjtGetChild(2).jjtGetChild(0), 0);
								if (TypeCast(left, right, false) >= 0)
								{
									boolean flag = false;
									for (int m = 2; m < child.jjtGetChild(2).jjtGetNumChildren(); m++)
									{
										int lleft = ((SimpleNode)map.get((Identifier)id).node.jjtGetChild(2).jjtGetChild(m).jjtGetChild(1)).getId();
										int rright = ((SimpleNode)child.jjtGetChild(2).jjtGetChild(m).jjtGetChild(1)).getId();
										//if (TypeCast(this.getChildNodeName((SimpleNode)map.get((Identifier)id).node.jjtGetChild(2).jjtGetChild(m), 1), this.getChildNodeName((SimpleNode)child.jjtGetChild(2).jjtGetChild(m), 1), true))
										if (TypeCast(lleft, rright, false) >= 0)
											continue;
										else
										{
											flag = true;
											break;
										}
									}
									if (flag == false)
										this.addErrorMessage(map, (SimpleNode)child.jjtGetChild(1), "Duplicate method definition.");
								}
							}
						}
						else {
							map.put(id, new CheckValue(child));
							localvar.add(id);
						}
						visit(map, new ArrayList<Identifier>(), child, true);
					}
				}
				break;			
				
			case XYZParserTreeConstants.JJTVARDECL://变量定义
				id = new Identifier(this.getChildNodeName(root, 1) ,((SimpleNode)root.jjtGetChild(0).jjtGetChild(0)).getId());
				if(map.containsKey(id)) 
					throw new DeclarationException(id.toString() + ":\t重复的变量定义.", root);
				map.put(id, new CheckValue(root));	
				localvar.add(id);
				break;
				
			case XYZParserTreeConstants.JJTMETHODDECL:{//函数{
//				Identifier tmpId = new Identifier(this.getChildNodeName((SimpleNode)root.jjtGetChild(2), 1),XYZParserTreeConstants.JJTMETHODDECL);
//				if(localvar.contains(tmpId))
//					this.addErrorMessage(map, (SimpleNode)root.jjtGetChild(2), "Duplicate local identify definition.");
//				else 
//					map.put(tmpId, new CheckValue(root));
				SimpleNode tempNode1, tempNode2;
				for (int i = 2; i < root.jjtGetNumChildren(); ++i) {
					tempNode1 = (SimpleNode)root.jjtGetChild(i);
					switch (tempNode1.getId()) {
					case XYZParserTreeConstants.JJTFORMALLIST://参数列表
						tempNode2 = (SimpleNode)tempNode1.jjtGetChild(1);
						id = new Identifier(this.getChildNodeName(tempNode1, 1), ((SimpleNode)tempNode1.jjtGetChild(0).jjtGetChild(0)).getId());
						if (localvar.contains(id))
							this.addErrorMessage(map, tempNode2, "Duplicate local identify definition.");
						else
							localvar.add(id);
						
						if (map.containsKey(id))
							coverMap.put(id, map.get(id));//参数覆盖列表
						map.put(id, new CheckValue(tempNode2));//新参数加入
						//if formalRest exists
						for (int j = 3; j < tempNode1.jjtGetNumChildren(); j+=2) {
							tempNode2 = (SimpleNode)tempNode1.jjtGetChild(j);
							id = new Identifier(this.getChildNodeName(tempNode2, 1), ((SimpleNode)tempNode2.jjtGetChild(0).jjtGetChild(0)).getId());
							if (localvar.contains(id))
								this.addErrorMessage(map, (SimpleNode)tempNode2.jjtGetChild(1), "Duplicate local identify definition.");
							else
								localvar.add(id);
							
							if (map.containsKey(id))
								coverMap.put(id, map.get(id));//参数覆盖列表
							map.put(id, new CheckValue(tempNode2));//新参数加入
						}
						break;
					case XYZParserTreeConstants.JJTPREDECL://pre语句
						this.CheckMatchType((SimpleNode)tempNode1.jjtGetChild(0), map);
						//this.expVisit(map, (SimpleNode)tempNode1.jjtGetChild(0));
						break;
					case XYZParserTreeConstants.JJTPOSTDECL://post语句
						postRoot = (SimpleNode)tempNode1.jjtGetChild(0);
						postExp = true;
						break;
					case XYZParserTreeConstants.JJTVARDECL://变量定义
						id = new Identifier(this.getChildNodeName(tempNode1, 1) ,((SimpleNode)tempNode1.jjtGetChild(0).jjtGetChild(0)).getId());
						if (localvar.contains(id))
							throw new DeclarationException(id.toString() + ":\t重复的变量定义.", tempNode1);
						localvar.add(id);
						
						if (map.containsKey(id))
							coverMap.put(id, map.get(id));
						
						map.put(id, new CheckValue(tempNode1));
						break;
					case XYZParserTreeConstants.JJTSTATEMENT://语句定义
						this.visit(map, localvar, (SimpleNode)tempNode1.jjtGetChild(0), false);
						break;
					case XYZParserTreeConstants.JJTRETURN://返回语句
						this.returnVisit(map, (SimpleNode)tempNode1.jjtGetChild(0), ((SimpleNode)root.jjtGetChild(0).jjtGetChild(0)).getId());
						break;
					}
				}
				
				if (postExp) {
					postExp = false;
					this.postVisit(map, postRoot);
				}

				break;
			}
			case XYZParserTreeConstants.JJTSTATEMENT://语句
				visit(map, localvar, (SimpleNode)root.jjtGetChild(0), false);			
				break;
			
			case XYZParserTreeConstants.JJTASSIGNMENTSTATEMENT: //赋值语句 
				idname = this.getChildNodeName(root, 0);
				if(this.GetIdType(idname, localvar) == -1)
					throw new DeclarationException(idname + ":\t未定义的变量.", root);

				this.CheckMatchType(root, map);
				break;
			
				
			case XYZParserTreeConstants.JJTARRAYASSIGNMENTSTATEMENT://数组赋值语句
				//id = new Identifier(this.getChildNodeName(root, 0) ,Identifier.ID_IDENTIFIER);
				idname = this.getChildNodeName(root, 0);
				if(this.GetIdType(idname, localvar) == -1)
					throw new DeclarationException(idname + ":\t未定义的变量.", root);

				this.CheckMatchType(root, map);
				break;
				
			case XYZParserTreeConstants.JJTIFSTATEMENT://If语句
				this.CheckMatchType((SimpleNode)root.jjtGetChild(0), map);
				visit(map, localvar, (SimpleNode)root.jjtGetChild(1), false);
				if(root.jjtGetNumChildren() > 2)
					visit(map, localvar, (SimpleNode)root.jjtGetChild(2), false);
				break;
				
			case XYZParserTreeConstants.JJTWHILESTATEMENT://while语句
				this.CheckMatchType((SimpleNode)root.jjtGetChild(0), map);
				visit(map, localvar, (SimpleNode)root.jjtGetChild(1), false);
				break;
			case XYZParserTreeConstants.JJTPRINTSTATEMENT://print语句
				visit(map, localvar, (SimpleNode)root.jjtGetChild(0), false);
				break;
			case XYZParserTreeConstants.JJTBLOCK://大括号
				for(int i = 0; i < root.jjtGetNumChildren(); i++)
					visit(map, new ArrayList<Identifier>(), (SimpleNode)root.jjtGetChild(i), true);
				break;
			case XYZParserTreeConstants.JJTEXPRESSION:
				this.CheckMatchType(root, map);
				break;
			}
		}
		catch (DeclarationException e) {
			this.errMsg += e.getMsg() + "\n";
		}
		
		if (revert) {
			Identifier mv;
			for (int i = 0; i < localvar.size(); ++i) {
				mv = localvar.get(i);
				if (coverMap.containsKey(mv))//若是覆盖的变量则恢复上层变量
					map.put(mv, coverMap.get(mv));
				else
					map.remove(mv);//否则直接删除
			}
		}
	}
	
	
	
	
	
//by zy, begin
	
	public  List<Identifier> doit(HashMap<Identifier, CheckValue> map)
	{
		Set set = map.keySet();
		List<Identifier> localvar = new ArrayList<Identifier>(set);
		return localvar;
	}

	
	//判断在运算、赋值语句中的类型是否匹配
	public int CheckMatchType(SimpleNode root,HashMap<Identifier,CheckValue> local) throws DeclarationException{
		int leftType,rightType,indexType;
		String leftName;
		int matchType = -1;
		
		switch(root.getId()){
		case XYZParserTreeConstants.JJTTHISEXPRESSION:
			break;
		case XYZParserTreeConstants.JJTMESSAGESEND: 
			matchType = this.callMethod(root, local);
			if(matchType < 0)
				throw new DeclarationException(((SimpleNode)root.jjtGetChild(0)).jjtGetFirstToken()+":未定义的方法.",root);
			break;
		case XYZParserTreeConstants.JJTASSIGNMENTSTATEMENT:
			leftName = ((SimpleNode)root.jjtGetChild(0)).jjtGetFirstToken().toString();
			leftType = this.GetIdType(leftName, (ArrayList<Identifier>)this.doit(local));
			if(leftType == -1)
				throw new DeclarationException(leftName+"：\t未定义的变量.",root);
			//get rightName and right Type:Expression iteration
			rightType = CheckMatchType((SimpleNode)root.jjtGetChild(1),local);// get rightType
			if(rightType > 0) {
				matchType = TypeCast(leftType,rightType,true);
				if(matchType < 0)
					throw new DeclarationException("赋值语句类型不匹配！",root);
			}
			else
				throw new DeclarationException("赋值语句类型不匹配！",root);
			break;
		case XYZParserTreeConstants.JJTARRAYASSIGNMENTSTATEMENT:
			leftName = ((SimpleNode)root.jjtGetChild(0)).jjtGetFirstToken().toString();
			leftType = this.GetIdType(leftName, (ArrayList<Identifier>)this.doit(local));
			if(leftType == -1)
				throw new DeclarationException(leftName+":\t未定义的变量.",root);
			indexType = CheckMatchType((SimpleNode)root.jjtGetChild(1),local); //test if it's int
			if(indexType != XYZParserTreeConstants.JJTINTEGERTYPE)
				throw new DeclarationException(leftName+":\t数组下标不是整数.",root);
			rightType = CheckMatchType((SimpleNode)root.jjtGetChild(2),local); //get rightType
			if(rightType > 0) {
				matchType = TypeCast(leftType,rightType,true);
				if(matchType < 0)
					throw new DeclarationException("赋值语句类型不匹配！",root);
			}
			else
				throw new DeclarationException("赋值语句类型不匹配！",root);
			break;
		case XYZParserTreeConstants.JJTEXPRESSION: 
			leftType = CheckMatchType((SimpleNode)root.jjtGetChild(0),local);//primaryExp
			rightType = CheckMatchType((SimpleNode)root.jjtGetChild(1),local);//temp
			matchType = TypeCast(leftType,rightType,false);
			if(matchType < 0)
				throw new DeclarationException("表达式类型不匹配！",root);
			break;
		case XYZParserTreeConstants.JJTPRIMARYEXPRESSION:{
			leftName = ((SimpleNode)root.jjtGetChild(0)).jjtGetFirstToken().toString();
			SimpleNode tmpNode = (SimpleNode)root.jjtGetChild(0);
			if(tmpNode.getId() == XYZParserTreeConstants.JJTBRACKETEXPRESSION){
				return this.CheckMatchType((SimpleNode)tmpNode.jjtGetChild(0), local);
			}
			if(tmpNode.getId() == XYZParserTreeConstants.JJTINTEGERLITERAL ||
					tmpNode.getId() == XYZParserTreeConstants.JJTLONGLITERAL)
				leftType = tmpNode.getId();
			else if(tmpNode.getId() == XYZParserTreeConstants.JJTTRUELITERAL ||
					tmpNode.getId() == XYZParserTreeConstants.JJTFALSELITERAL)
				leftType = XYZParserTreeConstants.JJTBOOLEANTYPE;
			else{
				leftType = this.GetIdType(leftName, (ArrayList<Identifier>)this.doit(local));
				if(leftType < 0) {
					if(this.searchClass(root, leftName) != null)
						leftType = XYZParserTreeConstants.JJTALLOCATIONEXPRESSION;
					else if(leftName.equals("this"))
						leftType = XYZParserTreeConstants.JJTTHISEXPRESSION;
					else throw new DeclarationException(leftName+":未声明的变量.\n",root);
				}
			}
			switch(leftType){
			case XYZParserTreeConstants.JJTINTEGERLITERAL:
			case XYZParserTreeConstants.JJTINTEGERTYPE:
				matchType = XYZParserTreeConstants.JJTINTEGERTYPE;
				break;
			case XYZParserTreeConstants.JJTLONGTYPE:
			case XYZParserTreeConstants.JJTLONGLITERAL:
				matchType = XYZParserTreeConstants.JJTLONGTYPE;
				break;
			default:
				matchType = leftType;
				break;
			}
		}
			break;
		case XYZParserTreeConstants.JJTTEMP:
			//运算符不考虑在类型计算范围内
			if(root.jjtGetNumChildren() == 0){
				return 0;
			}
			if(((SimpleNode)root.jjtGetChild(0)).getId() == XYZParserTreeConstants.JJTMESSAGESEND)
				leftType = CheckMatchType((SimpleNode)root.jjtGetChild(0),local);
			else leftType = CheckMatchType((SimpleNode)root.jjtGetChild(0).jjtGetChild(0),local);
			rightType = CheckMatchType((SimpleNode)root.jjtGetChild(1),local);
			if(rightType == 0) return leftType;
			matchType = TypeCast(leftType,rightType,false);
			if(matchType < 0)
				throw new DeclarationException("类型不匹配！",root);
			break;
		case XYZParserTreeConstants.JJTIDENTIFIER:
			leftName = root.jjtGetFirstToken().toString();
			leftType = this.GetIdType(leftName, (ArrayList<Identifier>)this.doit(local));
			matchType = leftType;
			if(matchType < 0)
				throw new DeclarationException("未声明的变量！",root);
			break;
		case XYZParserTreeConstants.JJTINTEGERLITERAL:
		case XYZParserTreeConstants.JJTINTEGERTYPE:
			matchType = XYZParserTreeConstants.JJTINTEGERTYPE;
			break;
		case XYZParserTreeConstants.JJTLONGLITERAL:
		case XYZParserTreeConstants.JJTLONGTYPE:
			matchType = XYZParserTreeConstants.JJTLONGTYPE;
			break;
		case XYZParserTreeConstants.JJTBOOLEANTYPE:
			matchType = XYZParserTreeConstants.JJTBOOLEANTYPE;
			break;
		default:
			return 0;
		}
		
		return matchType;
	}
	
	public int CheckFuncParam(SimpleNode formallist, SimpleNode explist, HashMap<Identifier,CheckValue>map){
		if(formallist.getId() != XYZParserTreeConstants.JJTFORMALLIST)
			return -1;
		int children = formallist.jjtGetNumChildren();
		try {
			if(children != explist.jjtGetNumChildren()+1)
				throw new DeclarationException("参数个数不匹配！",explist);
			if(((SimpleNode)formallist.jjtGetChild(0).jjtGetChild(0)).getId() != this.CheckMatchType((SimpleNode)explist.jjtGetChild(0), map))
				throw new DeclarationException(
						((SimpleNode)explist.jjtGetChild(0).jjtGetChild(1)).jjtGetFirstToken().toString()+
						":参数类型不匹配",explist);
			for(int i = 2; i < children; i++) {
				SimpleNode node = (SimpleNode)formallist.jjtGetChild(i).jjtGetChild(0).jjtGetChild(0);
				SimpleNode expnode = (SimpleNode)explist.jjtGetChild(i-1);
				if(node.getId() != this.CheckMatchType(expnode, map))
					throw new DeclarationException(expnode.jjtGetFirstToken().toString()+
							":参数类型不匹配",expnode);
			}
		}
		catch(DeclarationException e){
			this.errMsg += e.getMsg() + "\n";
		}
		return 0;
	}
	
	//判断两个类型是否可以匹配，关注了int和long类型的转换，对于boolean型只要不相同就是不匹配
	private int TypeCast(int left, int right, boolean isAssign){
		if(right == 0) return left;
		if(left == right)
			return left;
		if(left == XYZParserTreeConstants.JJTBOOLEANTYPE ||
				right == XYZParserTreeConstants.JJTBOOLEANTYPE)
			return -1;
		if(left == XYZParserTreeConstants.JJTTHISEXPRESSION)
			return right;
		//统一int,long的各种类型为integertype和longtype
		if(left == XYZParserTreeConstants.JJTINTARRAYTYPE ||
				left == XYZParserTreeConstants.JJTINTEGERTYPE)
			left = XYZParserTreeConstants.JJTINTEGERTYPE;
		else if(left == XYZParserTreeConstants.JJTLONGARRAYTYPE ||
				left == XYZParserTreeConstants.JJTLONGLITERAL)
			left = XYZParserTreeConstants.JJTLONGTYPE;
		if(right == XYZParserTreeConstants.JJTINTARRAYTYPE ||
				right == XYZParserTreeConstants.JJTINTEGERTYPE)
			right = XYZParserTreeConstants.JJTINTEGERTYPE;
		else if(right == XYZParserTreeConstants.JJTLONGARRAYTYPE ||
				right == XYZParserTreeConstants.JJTLONGLITERAL)
			right = XYZParserTreeConstants.JJTLONGTYPE;
		//开始判断
		if(isAssign){
			if(left+1 == right)
				return -1;
			if(left-1 == right)
				return left;
		}
		else{
			return (left > right?left:right);
		}
		return -1;
	}
	
	private int GetIdType(String name, ArrayList<Identifier> list) {
		int type = -1;
		for(int i = 0; i < list.size(); i++) {
			if(list.get(i).id.equals(name)){
				type = list.get(i).type;
				break;
			}
		}
		return type;
	}
	
	//end of zy
	
	
	
	
	
	private void postVisit(HashMap<Identifier, CheckValue> map,SimpleNode postExp) throws DeclarationException {
		//this.expVisit(map, postExp);
	}
	
	private void returnVisit(HashMap<Identifier, CheckValue> map,SimpleNode root, int methodType) throws DeclarationException{
		
		int returnType = this.CheckMatchType(root, map);
		//String returnType = this.expVisit(map, (SimpleNode)root.jjtGetChild(0));
		//int returnType = map.get(new Identifier(re,type)).node.getId();
		if (returnType < 0 || this.TypeCast(methodType, returnType, true) < 0)
			this.addErrorMessage(map, root, "Return Type Error!");
	}
	
	
	private void addErrorMessage(HashMap<Identifier, CheckValue> map, SimpleNode node, String exMessage) {
		Token tk = node.jjtGetFirstToken();
		this.errMsg += node.jjtGetFirstToken().toString() + ":\t" + exMessage + "\n" + 
			"at line " + tk.beginLine + ", column " + tk.beginColumn + "\n\n";
	}
	
	public String getErrorMessage() {
		if (this.errMsg.equals(""))
			return "Semantic Accept!";
		else
			return "\n---------------------ERRORS---------------------\n" + this.errMsg;
	}
	
	private class Identifier {
		public String id;
		public int type;
		
		public Identifier(String id, int type){
			this.id = id;
			this.type = type;
		}
		
		public boolean equals(Object o) {
			try {
				Identifier id = (Identifier)o;
				if (this.type != id.type)
					return false;
				else
					return this.id.equals(id.id);
			}
			catch (Exception e) {
				return false;
			}
		}
		
		public int hashCode() {
			return this.id.hashCode() + type;
		}
		
		public String toString() {
			return this.id + " Type = " + this.type;
		}
	}
	
	private class CheckValue {
		public SimpleNode node;
		public CheckValue(Node node) {
			this.node = (SimpleNode)node;
		}
	}
} 
